import { Component, JsonAsset, Node, Vec3, _decorator, tween } from 'cc';
import { JsonsCfg } from '../../../auto/JsonsCfg';
import { SpriteFramesCfg } from '../../../auto/SpriteFramesCfg';
import { ResLoader } from '../../../core/modules/res/ResLoader';
import { Match3ZiUE } from './Match3ZiUE';
import { ZiStack } from './ZiStack';
const { ccclass, property } = _decorator;

@ccclass('Match3UI')
export class Match3UI extends Component {

    @property(Node)
    private board: Node = null;

    @property(Node)
    private collectArea: Node = null;
    //位置占用数组
    private m_PlaceHolders: Match3ZiUE[] = [];

    /**所有的旗子都会添加到此数组中一次 */
    private m_ZiList: Match3ZiUE[] = [];
    private stacks: ZiStack[][] = [];

    static R(loader: ResLoader) {
        loader.addUI(Match3ZiUE);
        //预加载好所有花色资源
        for (let i = 1; i <= 30; ++i) {
            loader.addSpriteFrame(SpriteFramesCfg.pai(`pai-${i}`));
        }
    }

    /**增加旗子 */
    public addZi(ziUE: Match3ZiUE) {
        this.m_ZiList.push(ziUE);

        //加到棋子栈
        for (let r = 0; r < 6; r++) {
            for (let c = 0; c < 6; c++) {
                this.stacks[ziUE.row + r][ziUE.col + c].push(ziUE);
            }
        }
    }

    /**判断是否可以点击 */
    public calcClickable(ziUE: Match3ZiUE): boolean {
        let stack: ZiStack = null;
        for (let r = 0; r < 6; r++) {
            for (let c = 0; c < 6; c++) {
                stack = this.stacks[ziUE.row + r][ziUE.col + c];
                if (!stack.empty && stack.top !== ziUE) {
                    //有一个旗子栈顶不是该棋子，就说明被遮挡，不可点击
                    return false;
                }
            }
        }
        return true;
    }

    async start() {
        console.log("主玩法界面");
        this.m_ZiList = [];
        this.stacks = [];
        this.m_PlaceHolders = [];
        //初始化栈数据
        const COL = 7;
        const ROW = 10;
        //因为栈是6*6的格子
        const SPLIT = 6;
        //把这些棋子的栈都初始化
        for (let r = 0, rmax = ROW * SPLIT; r < rmax; ++r) {
            let row_stacks: ZiStack[] = [];
            this.stacks.push(row_stacks);
            for (let c = 0, cmax = COL * SPLIT; c < cmax; ++c) {
                row_stacks.push(new ZiStack());
            }
        }
        //获取关卡数据
        let jsonAsset = await gCtrl.res.loadAssetAsync(JsonsCfg.level(0), JsonAsset);
        const levelJson = jsonAsset.json as {
            zis: [col: number, row: number, style: number][]
        };

        let clickFunc = (clickZi: Match3ZiUE) => {
            let isClickable = this.calcClickable(clickZi);
            if (!isClickable) {
                return;
            }
            let ziCol = clickZi.col;
            let ziRow = clickZi.row;
            this.removeZi(clickZi);
            //目前表现是移动到collectArea节点下
            clickZi.node.setParent(this.collectArea, true);
            tween(clickZi.node)
                .to(0.15, { position: new Vec3(0, 0, 0) })
                .start();

            //下方刷新
            let stack: ZiStack = null;
            for (let r = 0; r < 6; r++) {
                for (let c = 0; c < 6; c++) {
                    stack = this.stacks[ziRow + r][ziCol + c];
                    if (!stack.empty) {
                        stack.top.setClickable(this.calcClickable(stack.top));
                    }
                }
            }
            this.tryCollectingZi(clickZi);
        }


        levelJson.zis.forEach(zi => {
            let ziUE = gCtrl.ui.instantiate(Match3ZiUE);
            ziUE.node.setParent(this.board);
            ziUE.init(zi[0], zi[1], zi[2], clickFunc);
            this.addZi(ziUE);
        });

        //刷新一次所有旗子的显示
        this.m_ZiList.forEach(ziUE => {
            ziUE.setClickable(this.calcClickable(ziUE));
        })
    }


    /**移除棋子 */
    public removeZi(ziUE: Match3ZiUE) {
        this.m_ZiList.splice(this.m_ZiList.indexOf(ziUE), 1);
        //棋子栈栈顶肯定是该棋子
        for (let r = 0; r < 6; r++) {
            for (let c = 0; c < 6; c++) {
                this.stacks[ziUE.row + r][ziUE.col + c].pop();
            }
        }
    }

    /**尝试收集棋子 */
    private tryCollectingZi(clickZi: Match3ZiUE): boolean {
        //已经有7个了
        if (this.m_PlaceHolders.length === 7) {
            return false;
        }
        //没有7个
        //1.从后往前找，有没有同花色的棋子，有就插入
        for (let i = this.m_PlaceHolders.length - 1; i >= 0; --i) {
            let zi = this.m_PlaceHolders[i];
            if (zi.style === clickZi.style) {
                //插入到zi后面
                this.m_PlaceHolders.splice(i + 1, 0, clickZi);
                //标记当前棋子是否和前面两个子形成了消除
                let elimination: Match3ZiUE[] = [];
                if (!zi.isMarkElimnate && (i >= 1) && (this.m_PlaceHolders[i - 1].style === clickZi.style) && !this.m_PlaceHolders[i - 1].isMarkElimnate) {
                    //形成消除
                    elimination.push(this.m_PlaceHolders[i - 1]);
                    elimination.push(zi);
                    elimination.push(clickZi);
                    //标记消除
                    elimination.forEach(it => it.isMarkElimnate = true);
                }

                clickZi.moveToTargetIndex(this.collectArea, i + 1, () => {
                    //检测清除或者失败逻辑
                    if (elimination.length > 0) {
                        //消除行为
                        let startIndex = -1;
                        elimination.forEach(it => {
                            if (startIndex == -1) {
                                startIndex = this.m_PlaceHolders.indexOf(it);
                            }
                            it.node.destroy();
                        })
                        for (let z = startIndex + 3; z < this.m_PlaceHolders.length; z++) {
                            this.m_PlaceHolders[z].changeMoveingTargetIndex(z - 3);
                        }
                        this.m_PlaceHolders.splice(startIndex, 3);
                    } else {
                        this.checkLose();
                    }
                })
                //后面的棋子如果正在做飞行动画，更改目标
                for (let j = i + 2; j < this.m_PlaceHolders.length; ++j) {
                    this.m_PlaceHolders[j].changeMoveingTargetIndex(j);
                }
                return true;
            }
        }

        //2.找不到花色，那么直接插入
        this.m_PlaceHolders.push(clickZi);
        clickZi.moveToTargetIndex(this.collectArea, this.m_PlaceHolders.length - 1, () => {
            //检测消除或者失败逻辑
            this.checkLose();
        })
        return true;
    }

    private m_IsLose: boolean = false;

    /**检测消耗 */
    private checkLose(): void {
        if (this.m_PlaceHolders.length < 7) {
            return;
        }
        for (let i = 0; i < this.m_PlaceHolders.length; ++i) {
            if (this.m_PlaceHolders[i].isMarkElimnate) {
                return;
            }
        }
        //失败
        if (this.m_IsLose) {
            return;
        }
        this.m_IsLose = true;
        console.log("游戏失败弹窗");
    }
}


